﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using ColladaLoader;
using SlimDX;
using SlimDX.Direct3D10;

namespace SCS.GFX
{
    class XFile
    {
        public MeshContainer m;
        private MeshObject MO;

        int VertCount;
        float[,] Verts;
        List<SkinnedTangentVertex> VertexList;

        int FaceCount;
        int[,] Faces;
        List<int[]> Tris;
        int TrisCount;

        string texturefile;

        int UVCount;
        float[,] UVs;

        public XFile(String filename)
        {
            m = new MeshContainer();
            m.Name = filename;

            Console.WriteLine("Parsing XFile : " + filename);
            TextReader File = new StreamReader(filename);
            string line;

            #region parse file data
            while ((line = File.ReadLine()) != null)
            {
                //Console.WriteLine(line);
                #region vertex & faces
                if (line.Contains("Mesh ")&&line.Contains("{"))
                {
                    Console.WriteLine("mesh found");
                    string nextLine = File.ReadLine().Replace(";", "");
                    VertCount = int.Parse(nextLine);

                    Console.WriteLine("found" + VertCount.ToString() + " verts");

                    Verts = new float[VertCount, 3];

                    for (int i=0; i < VertCount; i++)
                    {
                        string[] vertcomponents = new string[3];
                        
                        nextLine = File.ReadLine();

                        string[] splitter = new string[1];
                        splitter[0] = ";";

                        vertcomponents = nextLine.Split(splitter,3,StringSplitOptions.None);

                        for (int j = 0; j < 3; j++)
                        {
                            vertcomponents[j] = vertcomponents[j].Replace(";", "");
                            vertcomponents[j] = vertcomponents[j].Replace(",", "");
                            Verts[i, j] = float.Parse(vertcomponents[j], System.Globalization.CultureInfo.InvariantCulture);
                        }

                    }
                    Console.WriteLine("verts parsed");

                    nextLine = "";

                    while (nextLine == "")
                    {
                        nextLine = File.ReadLine().Replace(";", "");
                    }
                    FaceCount = int.Parse(nextLine);
                    Console.WriteLine(nextLine + "n faces found");

                    Faces = new int[FaceCount, 5];
                    for (int i = 0; i < FaceCount; i++)
                    {
                        string[] Facecomponents = new string[5];

                        nextLine = File.ReadLine();

                        string[] splitter = new string[2];
                        splitter[0] = ";";
                        splitter[1] = ",";

                        Facecomponents = nextLine.Split(splitter, 5, StringSplitOptions.RemoveEmptyEntries);


                        for (int j = 0; j < Facecomponents.Length; j++)
                        {
                            Facecomponents[j] = Facecomponents[j].Replace(";", "");
                            Facecomponents[j] = Facecomponents[j].Replace(",", "");
                            Faces[i, j] = int.Parse(Facecomponents[j]);
                        }

                    }
                    Console.WriteLine("Faces parsed");
                }

                //In .X files, sometimes faces are stored as quads, therefore we have to split em up in 2 triangles
                Tris = new List<int[]>();
                for (int i = 0; i < FaceCount; i++)
                {
                    int[] temp = new int[5];
                    
                    for (int j = 0; j < 5; j++)
                      temp[j] = Faces[i,j];

                    if (temp[0] == 3)
                    {
                        int[] Triangle = new int[3];
                        Triangle[0] = temp[1];
                        Triangle[1] = temp[3];
                        Triangle[2] = temp[2];

                        Tris.Add(Triangle);

                    }
                    else if (temp[0] == 4)
                    {
                        int[] Triangle = new int[3];
                        Triangle[0] = temp[1];
                        Triangle[1] = temp[3];
                        Triangle[2] = temp[2];

                        Tris.Add(Triangle);
                        Triangle = new int[3];

                        Triangle[0] = temp[3];
                        Triangle[1] = temp[1];
                        Triangle[2] = temp[4];

                        Tris.Add(Triangle);

                    }

                }







                #endregion

                #region texture
                if (line.Contains("TextureFilename")) {
                    if (line.Contains("\""))
                    {
                        texturefile = line.Substring(line.IndexOf("\"") + 1);
                        texturefile = texturefile.Substring(0, texturefile.IndexOf("\""));
                    }
                    else
                    {
                        string nextLine = File.ReadLine();

                        texturefile = nextLine.Substring(nextLine.IndexOf("\"") + 1);
                        int index = texturefile.IndexOf("\"");
                        texturefile = texturefile.Substring(0, index);

                    }
                }
                #endregion

                #region UVs
                if (line.Contains("MeshTextureCoords {"))
                {
                    string nextLine = File.ReadLine().Replace(";", "");
                    UVCount = int.Parse(nextLine);
                    UVs = new float[UVCount, 2];

                    for (int i = 0; i < UVCount; i++)
                    {
                        string[] uvcomponents = new string[3];

                        nextLine = File.ReadLine();

                        string[] splitter = new string[1];
                        splitter[0] = ";";

                        uvcomponents = nextLine.Split(splitter, 3, StringSplitOptions.None);

                        for (int j = 0; j < 2; j++)
                        {
                            uvcomponents[j] = uvcomponents[j].Replace(";", "");
                            uvcomponents[j] = uvcomponents[j].Replace(",", "");
                            UVs[i, j] = float.Parse(uvcomponents[j], System.Globalization.CultureInfo.InvariantCulture);
                        }

                    }

                    Console.WriteLine("UV's parsed");

                }
                #endregion
            }
            #endregion

            File.Close();

            #region construct final data
            VertexList = new List<SkinnedTangentVertex>();

            TrisCount = Tris.Count;

            // Construct data
            m.textures.Add(texturefile);

            m.vertices.Clear();
            // Initialize reuseVertexPositions and reverseReuseVertexPositions
            // to make it easier to use them below
            m.reuseVertexPositions = new int[TrisCount * 3];
            m.reverseReuseVertexPositions = new List<int>[VertCount];
            for (int i = 0; i < m.reverseReuseVertexPositions.Length; i++)
                m.reverseReuseVertexPositions[i] = new List<int>();

            int Count = 0;
            foreach (int[] index in Tris)
            {
                Vector3 pos;
                Vector2 uv;

                Vector3 normal = new Vector3(0.0f, 0.0f, 0.0f);
                Vector3 tangent = new Vector3(0.0f, 0.0f, 0.0f);
                Vector3 blendweights = new Vector3(0.0f, 0.0f, 0.0f);
                Vector3 blendindices = new Vector3(0.0f, 0.0f, 0.0f);

                for (int i = 0; i < 3; i++)
                {
                    bool swapZY = true;

                    if (swapZY)
                      pos = new Vector3(Verts[index[i], 0], Verts[index[i], 2], Verts[index[i], 1]);
                    else
                      pos = new Vector3(Verts[index[i], 0], Verts[index[i], 1], Verts[index[i], 2]);
                    uv = new Vector2(UVs[index[i], 0], -1*UVs[index[i], 1]);
                    m.vertices.Add(new SkinnedTangentVertex(pos, blendweights, blendindices, uv, normal, tangent));


                    // Remember pos for optimizing the vertices later more easily.
                    m.reuseVertexPositions[Count] = index[i]; // pos / 3;
                    m.reverseReuseVertexPositions[index[i]].Add(Count);

                    Count++;

                }

            }







            #endregion

            m.GenerateVertexAndIndexBuffers();

            MO = new TexturedMeshObject(m);

        }

        public void Render(RenderInfo info)
        {
            MO.Render(info);
        }
    }
}
